home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
assemblr
/
library
/
sampler0
/
sdir24c.asm
< prev
next >
Wrap
Assembly Source File
|
1984-02-06
|
47KB
|
930 lines
TITLE SDIR - SORTED DIRECTORY COMMAND, Version 2.4
PAGE 64,132 ; JAN 1983
COMMENT |
SDIR [d:][path][filename[.ext]] [options] 2.4
[filespec] same as for DIR command
[options] * /A - List hidden files.
* /E - Without screen erase.
* /P - Pause when screen full.
/X - Sort by extension.
/S - Sort by size.
/D - Sort by date/time.
/N - Do not sort, original order.
Default = *.* sorted by name.ext with screen erase.
* - Option may be combined with other options.
This source file was created from an object file obtained
from Gene Plantz's BBS in Chicago. The original file name
was SD.HEX. I then used DEBUG and CAPTURE to get the first
dis-assembly which was then edited with WORDSTAR to create
a source that when assembled using MASM would duplicate the
original object file.
Comments have been added and I do hope they are helpful.
I have made several modifications to the first version and
am continuing to add comments. This source file is an
excellent example for anyone wishing to learn 8086/8088
assembly language. Use at your own risk and feel free to
share this file with your friends.
I certainly wish that John Chapman would publish his
source file. His comments are sure to be more meaningful
than mine could ever be. Some of the conversion routines
are very elegant, but difficult to understand. As far as
I'm concerned, PRINTDD is magic.
Several modifications have been made. They are:
1. Filespecs are processed like DIR does.
2. No sort option was added. /N
3. Pause when screen full option added. /P
4. Number of files found is printed.
Ted Reuss
Houston, TX
SDIR Version 2.2 The GETFREE Subroutine was updated for DOS 2.0
April 1, 1983 by Jack Y. Fong
Changes are denoted by "JYF" at the end of changed lines.
SDIR Version 2.3:
Added display of current directory name and volume name
in header lines for DOS Release 2.0.
Added total of file sizes for the displayed files.
This is helpful in DOS 2.0 since it allows you to determine
the number of bytes used by all the files in a root or
subdirectory (or used by a specified subset of
the files in a root or subdirectory).
John F. Ratti 29 June, 1983
Changes are denoted by "2.3" at the end of the changed lines.
SDIR Version 2.4:
Added display of attribute byte. The column 'ATR' will display
up to 4 attribute codes. The codes are as follows:
A - Archive bit is off (file has been archived)
H - Hidden bit is on (file is hidden)
R - Read-only bit is on (file is read-only)
S - System bit is on (file is a system file)
Corrected display of hidden, system, read-only and directory
entries when /a option is specified.
Added pathname capability. Any pathname that DIR will accept
will work. The code should have been rewritten, rather than
modified. The resulting code is somewhat obtuse, and I
apologize for it. I plan to write a proper pathname
parser. When I do, I'll incorporate it into SDIR.
This version MUST be used under MS-DOS release 2.0.
John F. Ratti 03 July, 1983
Changes are denoted by "2.4" at the end of the changed lines.
|
SUBTTL EQUATES & STRUCTURES
PAGE
IF1
DOSCALL MACRO FUNC,PARM1
.xcref
F_C = FUNC
IFNB <PARM1>
IF F_C EQ 2 OR (F_C GE 4 AND F_C LE 6) OR F_C EQ 14 OR F_C EQ 46
MOV DL,PARM1
ELSE
MOV DX,OFFSET PARM1
ENDIF
ENDIF
MOV AH,FUNC
INT 21H
.cref
ENDM
ENDIF
.SALL ;supress all macro expansions
; PC-DOS INTERRUPT 21H FUNCTION CODES
;
@CHROUT EQU 2 ;display char in DL
@KEYIN EQU 8 ;kybd input w/o echo
@STROUT EQU 9 ;print string terminated with $
@CKEYIN EQU 12 ;clr kybd bufr & do inp.func in AL
@OPEN EQU 15 ;open XFCB 2.4
@SRCH1 EQU 17 ;search for first dir entry
@SRCH2 EQU 18 ;search for next dir entry
@GETDSK EQU 25 ;get default disk drive
@SETDTA EQU 26 ;set disk transfer addr
@FATAD2 EQU 28 ;get FAT of drive # in DL
@PARSEF EQU 41 ;parse filename
@GETDTE EQU 42 ;get system date
@GETTME EQU 44 ;get system time
@GETVER EQU 30H ;get version number JYF
@CTLBRK EQU 33H ;get/set ctrl/break checking 2.4
@DSKFSP EQU 36H ;get disk free space JYF
@CHDIR EQU 3BH ;change directory 2.4
@CHMOD EQU 43H ;change/get file mode 2.4
@GETCD EQU 47H ;get current directory 2.3
@FIND1 EQU 4EH ;find first dir. entry (DOS 2.0) 2.4
@FIND2 EQU 4FH ;find next dir entry (DOS 2.0) 2.4
CR EQU 0DH ;carriage return
LF EQU 0AH ;line feed
FCB_1 EQU 5CH ;fcb for parameter 1
PARAM_L EQU 80H ;# characters in PARAM_B
PARAM_B EQU 81H ;DOS cmd parameter buffer.
; PC-DOS packed date <yyyyyyym mmmddddd>
P_DTE RECORD P_YR:7,P_MO:4,P_DY:5
; PC-DOS packed time <hhhhhmmm mmmsssss>
P_TME RECORD P_HR:5,P_MI:6,P_2S:5
DIR RECORD P_YR:7,P_MO:4,P_DY:5
; PC-DOS packed time <hhhhhmmm mmmsssss>
P_TME RECORD P_HR:5,P_MI:6,P_2S:5
DIRNTRY STRUC ;directory entry structure
LNK DW 0 ;ptr to next entry
NAM DB 8 DUP(0),'.' ;filename
EXT DB 3 DUP(0) ;extension
TME DW 0 ;time
DTE DW 0 ;date
SZL DW 0 ;low word of size
SZH DW 0 ;high word of size
ATR DB 0 ;attribute byte 2.4
DIRNTRY ENDS
SUBTTL DATA AREA & INITIALIZATION
PAGE
SDIR SEGMENT PUBLIC 'CODE'
ASSUME CS:SDIR,DS:SDIR,ES:SDIR
ORG 100H
MAIN PROC FAR
JMP STARTS
DIRLNK DW DIRBUF ;ptr to next opening in DIRBUF
C1LNK DW 0 ;ptr to row 1, column 1
C2LNK DW 0 ;ptr to row 1, column 2
NBRFILS DW 0 ;# of files or detail lines
SRTFLG DB 0 ;if = 0 then sort else no sort
CLSFLG DB 0 ;if = 0 then clear screen
EXTFLG DB 0 ;if <> 0 then sort by ext
SIZFLG DB 0 ;if <> 0 then sort by size
DTEFLG DB 0 ;if <> 0 then sort by date/time
PSEFLG DB 0 ;if <> 0 then pause if screen full
LPERSCR EQU 25 ;Lines per screen
LINCNT DB LPERSCR-5 ;Number of lines left
PSEMSG DB 'Strike a key when ready . . . $'
HDNG1 DB 'SDIR: Sorted DIRectory listing, Version 2.4 '; 2.3
DB 'Volume ' ; 2.3
VOLNAME DB ' ' ; 2.3
D_MM DW '00' ;Month
DB '/'
D_DD DW '00' ;Day
DB '/'
D_YY DW '00' ;Year
DB ' '
T_HH DW '00' ;Hours
DB ':'
T_MM DW '00' ;Minutes
DB CR,LF,'$' ; 2.3
HDNG2 DB 32 DUP(' ') ; 2.3
DB 'Directory of ' ; 2.3
HDRVE DB '@:' ; 2.3
DIRNAME DB '\',69 DUP(0) ; directory name 2.4
DB LF,LF,CR,'$' ; 2.3
CRLF DB CR,LF,'$'
LFLFCR DB LF,LF,CR,'$' ;literal for a blank line 2.3
HDNG3 DB 'FILESPEC.EXT BYTES ATR -LAST CHANGE-$'
DB 8 DUP(' ')
SPACES DB '$'
HDNG4 DB ' Bytes in $' ; 2.3
HDNG5 DB ' File(s); ','$' ; 2.4
HDNG6 DB ' bytes free.',CR,LF,'$' ; 2.4
SUBTTL DISK TRANSFER AREA & FREE SPACE ENTRY DEFS
PAGE
DB 'PATH NAME='
PATHD DB '@:'
PATH DB 64 DUP(0) ;hold area for pathname 2.4
XFCB DB -1,7 DUP(0),11 DUP('?'),25 DUP(0)
ATTRIB EQU XFCB+6 ;file attribute
DRVNUM EQU ATTRIB+1 ;drive # (1=A, 2=B, etc.)
DTA DB 40 DUP(0) ;Disk Transfer Area used
XNAME EQU DTA+8 ;volume name 2.4
FILNAME EQU DTA+30 ;by FIND for the 2.4
FILTIME EQU DTA+22 ;directory search. 2.4
FILSIZE EQU DTA+26 ; 2.4
FILATTR EQU DTA+21 ;(file attribute byte) 2.4
FREESPC DW 0 ;Free space entry.
DB '*FREE SPACE*',4 DUP(0)
LOSIZE DW 0 ;of free space
HISIZE DW 0 ;of free space
LOTOTAL DW 0 ;total size of all files: low word 2.3
HITOTAL DW 0 ;total size of all files: high word 2.3
PATHLEN DW 0 ;length of subdirectories in pathname 2.4
HOLDATR DB 0 ;hold area for XFCB attribute byte 2.3
HOLDLEN DW 0 ;hold area for length of directory name 2.3
DBLCNT DW 0 ;current offset into DOUBLE 2.4
DOUBLE DB 8 DUP(' '),'$' ;destination for PRINTDX 2.4
PRTATR DB 5 DUP(' '),'$' ;area to build ATR for printing 2.4
INITATR DB 5 DUP(' ') ;used to re-init ATR 2.4
PRTDIR 2DB ' <DIR>$' ;literal used to denote directories 2.4
ALLF DB '*.*' ;literal for displaying all files 2.4
PATHALL DB '\*.*',0 ;same as above for subdirectories 2.4
DRVNBR DB 0 ;place to hold working drive number 2.4
CURDSK DB '@:\' ;hold area for current dirname so we can2.4
CURDIR DB 64 DUP(0) ;restore it later 2.4
PATHNF DB 'Path not found$' ;error message literal 2.4
SUBTTL MAIN PROGRAM SECTION
PAGE
STARTS:
PUSH DS ;Set up the
XOR AX,AX ; stack for a
PUSH AX ; return to DOS.
CALL GETARGS ;Process arguments
CALL SRCHDIR ;Search directory
CMP SRTFLG,0 ;Check if any sort
JZ A1 ; option selected.
CALL LNKDIRB ;Leave in original
JMP SHORT A2 ; directory order.
A1: CALL SRTDIRB ;Sort by major key
A2: CALL GETFREE ;Get free space
CALL SPLTLST ;Set up for 2 columns
CALL PRTHDNG ;Print headings
CALL PRTDRVR ;Print detail lines
CALL PRTNFLS ;Print byte total and # of files 2.3
RET ;Return to DOS
MAIN ENDP
SUBTTL GETARGS - PROCESS ARGUMENTS
PAGE
GETARGS PROC NEAR
MOV DI,PARAM_L ;point to command buffer length 2.4
XOR CH,CH ;clear high-order byte 2.4
MOV CL,BYTE PTR [DI] ;get length 2.4
JCXZ G24F ;jump if no param provided 2.4
INC DI ;point to command buffer 2.4
MOV AL,' ' ;we'll search for the first non-blank 2.4
CLD ;search forward 2.4
REPE SCASB ;find first non-blank 2.4
JE G24F ;all blanks: treat like no parm provided2.4
INC CX ;and adjust length 2.4
DEC DI ;adjust offset 2.4
MOV SI,DI ;save offset of first non-blank 2.4
MOV DX,CX ;save cx 2.4
MOV AL,'/' ;search for a slash 2.4
REPNE SCASB ;search for a slash 2.4
JCXZ G24A ;jump if slash not found 2.4
INC CX ;adjust cx if slash found 2.4
G24A: NEG CX ;subtract count from original length 2.4
ADD CX,DX ;to get length of drive+path 2.4
JCXZ G24F ;if 0, only options specified 2.4
MOV DI,OFFSET PATH ;point to path name hold area 2.4
CMP BYTE PTR [SI+1],':' ;was drive number specified? 2.4
JNE G24B ;No, go move the path 2.4
INC SI ;point past drive number 2.4
INC SI ;point past : 2.4
DEC CX ;adjust... 2.4
DEC CX ;...length 2.4
JNZ G24B ;if any characters remain process them 2.4
G24F: MOV SI,OFFSET ALLF ;point to the all-files literal 2.4
MOV DI,OFFSET PATH ;the path needs it 2.4
MOV CX,3 ;length of literal 2.4
CLD ;to assure forward direction 2.4
REP MOVSB ;move the literal 2.4
JMP G24C ;now process normally 2.4
G24B: CLD ;clear direction flag 2.4
MOV DX,CX ;save the length 2.4
REP MOVSB ;and move the pathname to path 2.4
CMP DX,1 ;is length of pathname 1? 2.4
JNE G24C ;no 2.4
CMP PATH,'\' ;is the only character a backslash? 2.4
JNE G24C ;no 2.4
MOV SI,OFFSET ALLF ;point to the all-files literal 2.4
MOV DI,OFFSET PATH+1 ;the path needs it 2.4
MOV CX,3 ;length of literal 2.4
CLD ;to assure forward direction 2.4
REP MOVSB ;move the literal 2.4
G24C: MOV SI,PARAM_B ;point to cmd buffer 2.4
MOV DI,OFFSET DRVNUM ;point to FCB 2.4
MOV AL, 1111B ;Select parse options
DOSCALL @PARSEF ;Parse filename
CMP BYTE PTR [DI],0 ;If <> 0 then
JNZ B1 ; not default drive
DOSCALL @GETDSK ;AL <- default disk
INC AL ;Increment drive #
STOSB ;Save drive #
B1: MOV AL,DRVNUM ;get drive number 2.4
MOV DRVNBR,AL ;save as working drive number 2.4
ADD PATHD,AL ;convert drive number to ascii 2.4
XOR CX,CX ;clear cx just in case... 2.4
MOV AX,0 ;load "get attribute" subfunction code 2.4
DOSCALL @CHMOD,PATHD ;get attribute of the current path in cx2.4
OR AL,AL ;check for error 2.4
JNZ G24X ;if so, it's not a directory 2.4
TEST CX,10H ;is it a directory? 2.4
JZ G24X ;no 2.4
MOV DI,OFFSET PATH ;we need to find the end of PATH 2.4
MOV CX,64 ;which can be up to 64 bytes long... 2.4
MOV AL,0 ;...so we'll search for a 0 2.4
CLD ;search forward 2.4
REPNE SCASB ;find the end of PATH 2.4
DEC DI ;point di at the zero 2.4
MOV SI,OFFSET PATHALL ;point to literal 2.4
MOV CX,5 ;literal is 5 bytes long 2.4
CLD ;i'm a coward 2.4
REP MOVSB ;now move the literal to the path 2.4
G24X: MOV CX,64 ;up to 64 characters in a pathname 2.4
MOV AL,'\' ;we'll search for the last backslash 2.4
MOV DI,OFFSET PATH+63 ;point to the end of the pathname 2.4
STD ;search backwards 2.4
REPNE SCASB ;for the last backslash 2.4
MOV PATHLEN,CX ;and save path length 2.4
CMP PATH,'\' ;is first path character a backslash? 2.4
JNE G24D ;no, full path not specified 2.4
MOV CX,PATHLEN ;get the length of the subdirectories 2.4
MOV SI,OFFSET PATH ;point to path 2.4
MOV DI,OFFSET DIRNAME ;and to dest 2.4
CLD ;just in case 2.4
REP MOVSB ;move the pathname 2.4
JMP G24E ;bypass the rest of this 2.4
G24D: MOV SI,OFFSET DIRNAME+1 ;point to directory name field 2.4
MOV DL,BYTE PTR DRVNBR ;pick up drive number 2.4
DOSCALL @GETCD ;get the current directory 2.4
MOV CX,PATHLEN ;if pathlen is zero, no subdirectories 2.4
JCXZ G24E ;so don't concatenate path 2.4
MOV CX,64 ;we're going to find the end of... 2.4
MOV AL,0 ;...DIRNAME so we can concatenate... 2.4
MOV DI,OFFSET DIRNAME ;...the path subdirectories to it 2.4
CLD ;search forwards 2.4
REPNE SCASB ;search for a 0 2.4
DEC DI ;point back to the zero 2.4
DEC DI ;point to last character of current dir 2.4
CMP BYTE PTR [DI],'\' ;is the last character a backslash? 2.4
JNE G24Z ;no, it's not a root directory 2.4
INC DI ;adjust pointer 2.4
JMP G24Y ;and skip extra-separator stuff 2.4
G24Z: INC DI ;adjust pointer 2.4
MOV AL,'\' ;get a literal 2.4
STOSB ;to separate the 2 concatenated parts 2.4
G24Y: MOV CX,PATHLEN ;get length of subdirectories 2.4
MOV SI,OFFSET PATH ;move from path to dirname 2.4
CLD ;forward move 2.4
REP MOVSB ;now concatenate the dir + pathnames 2.4
G24E: MOV AL,0 ;read ctrl/break state into dl 2.4
DOSCALL @CTLBRK ;read status 2.4
PUSH DX ;save status 2.4
MOV AL,1 ;prepare to set ctl/break state... 2.4
MOV DL,0 ;...to OFF... 2.4
DOSCALL @CTLBRK ;...so we won't mess up the current dir 2.4
MOV DL,BYTE PTR DRVNBR ;get drive number 2.4
ADD CURDSK,DL ;convert to ascii 2.4
ADD HDRVE,DL ;convert to ascii 2.4
MOV SI,OFFSET CURDIR ;point to current directory save area 2.4
DOSCALL @GETCD ;get and save current directory 2.4
DOSCALL @CHDIR,HDRVE ;temporarily set current directory 2.4
CMP AL,3 ;check for error return 2.4
JNE G24Q ;jump if no error 2.4
DOSCALL @STROUT,PATHNF ;issue 'path not found message' 2.4
INT 20H ;and get lost 2.4
G24Q: MOV DL,BYTE PTR DRVNBR ;get drive number 2.4
MOV SI,OFFSET DIRNAME+1 ;point to dirname 2.4
DOSCALL @GETCD ;now get the dirname without '\..'s 2.4
DOSCALL @CHDIR,CURDSK ;now reset the current directory 2.4
MOV AL,1 ;set ctrl/break state... 2.4
POP DX ;...to previous value 2.4
DOSCALL @CTLBRK ;and do it 2.4
MOV DI,OFFSET DIRNAME ;point to directory name field again 2.4
MOV CX,64 ;name can be up to 64 bytes long 2.4
MOV AL,0 ;name is terminated by a zero 2.4
CLD ;just in case 2.4
REPNE SCASB ;search for the end 2.4
MOV AX,64 ;get constant 2.4
SUB AX,CX ;subtract remaining count 2.4
SHR AX,1 ;divide result by 2 2.4
MOV HOLDLEN,AX ;and save result 2.4
DEC DI ;adjust pointer 2.4
MOV CX,4 ;load length of literal 2.4
MOV SI,OFFSET LFLFCR ;point to literal 2.4
CLD ;just in case 2.4
REP MOVSB ;and terminate the dirname with literal 2.4
MOV SI,PARAM_L ;SI <- ptr cmd length
MOV CH,0
MOV CL,[SI] ;CL <- # chars in cmd
JCXZ B10
B2: INC SI ;Point to next char
CMP BYTE PTR [SI],'/'
JNZ B8 ;If not a slash
MOV AL,[SI+1] ;AL <- option letter
AND AL,0DFH ;Force to upper-case
CMP AL,'A' ;Hidden & system & directory files?
JNZ B3 ;Nope, try next one.
MOV HOLDATR,2+4+16 ;Hidden & system & directory
B3: CMP AL,'E' ;Without screen erase?
JNZ B4 ;Nope, try next one.
MOV CLSFLG,AL
B4: CMP AL,'S' ;Sort by size?
JNZ B5 ;Nope, try next one.
MOV SIZFLG,AL
B5: CMP AL,'D' ;Sort by date/time?
JNZ B6 ;Nope, try next one.
MOV DTEFLG,AL
B6: CMP AL,'X' ;Sort by extension?
JNZ B7 ;Nope, try next one.
MOV EXTFLG,AL
B7: CMP AL,'N' ;Original order?
JNZ B8 ;Nope, try next one.
MOV SRTFLG,AL
B8: CMP AL,'P' ;Pause when screen full?
JNZ B9 ;Nope, try next one.
MOV PSEFLG,AL
B9: LOOP B2 ;Test for another param.
B10: RET
GETARGS ENDP
SUBTTL SRCHDIR - SEARCH DIRECTORY
PAGE
SRCHDIR PROC NEAR
DOSCALL @SETDTA,DTA ;Set DTA for dir. search 2.3
MOV CX,11 ;we'll move 11... 2.4
MOV AL,'?' ;...question marks... 2.4
MOV DI,OFFSET XFCB+8 ;...to the XFCB... 2.4
CLD ;...in case the filename is crashed... 2.4
REP STOSB ;...so that we can search for the volid 2.4
MOV BYTE PTR ATTRIB,8 ;set attribute byte and... 2.3
DOSCALL @SRCH1,XFCB ;get the volume name 2.3
MOV SI,OFFSET XNAME ;point to filename within xfcb 2.4
MOV CX,11 ;load length of volume name 2.3
MOV DI,OFFSET VOLNAME ;point to destination field in HDNG1 2.3
CLD ;forward, march 2.3
REP MOVSB ;move the volume name 2.3
MOV DI,OFFSET DIRNAME ;point to the directory name again 2.3
MOV CL,HOLDATR ;get the real attribute byte 2.4
XOR CH,CH ;clear the high-order byte 2.4
DOSCALL @FIND1,PATHD ;First call to search dir. 2.4
C1: OR AL,AL
JNZ C2 ;Not found, quit looking.
MOV BX,DIRLNK ;BX <- base of DIRBUF
LEA DI,[BX].NAM ;point to beginning of dirntry 2.4
MOV SI OFFSET FILNAME
MOV CX,12 ;length of filename 2.4
CMP BYTE PTR [SI],'.' ;is first character a period? 2.4
JNE C24A ;no, it's not a special case 2.4
MOVSB ;move it to the buffer 2.4
DEC CX ;adjust count 2.4
CMP BYTE PTR [SI],'.' ;is next character a period? 2.4
JNE C24A ;no, let normal routine pad the rest 2.4
MOVSB ;move it to the buffer 2.4
DEC CX ;adjust count 2.4
C24A: CMP BYTE PTR [SI],0 ;is it a zero? 2.4
JNE C24B ;no 2.4
MOV AL,' ' ;load a space into al 2.4
REP STOSB ;and blank out the rest of the name 2.4
JMP C24X ;and go get other fields 2.4
C24B: CMP BYTE PTR [SI],'.' ;is it a period? 2.4
JNE C24C ;no, process it 2.4
MOV DX,CX ;save CX 2.4
SUB CX,4 ;determine number of spaces needed 2.4
SUB DX,CX ;adjust saved CX 2.4
MOV AL,' ' ;get a space 2.4
REP STOSB ;and pad out the name 2.4
MOV CX,DX ;restore CX 2.4
C24C: MOVSB ;move the character to the buffer 2.4
DEC CX ;adjust count 2.4
JNZ C24A ;and loop if anything's left to process 2.4
C24X: MOV SI,OFFSET FILTIME ;exit point for filename routine 2.4
MOVSW ;Move time to DIRBUF
MOVSW ;Move date to DIRBUF
MOV SI,OFFSET FILSIZE
MOVSW ;Move size to DIRBUF
MOVSW
MOV SI,OFFSET FILATTR ;point to file attribute byte 2.4
MOVSB ;and move it to dirntry 2.4
ADD BX,SIZE DIRNTRY ;Point to next entry
MOV DIRLNK,BX ;Save ptr
INC NBRFILS ;Increment file count
MOV CL,HOLDATR ;get the real attribute byte 2.4
XOR CH,CH ;clear the high-order byte 2.4
DOSCALL @FIND2,PATHD ;Search for next file 2.4
JMP C1 ;Loop for next one
C2: RET
SRCHDIR ENDP
SUBTTL SRTDIRB - SORTS ENTRIES IN DIRBUF
PAGE
SRTDIRB PROC NEAR ;Sorts directory entries in DIRBUF
MOV DI,OFFSET DIRBUF ;Point to DIRBUF
D1: CMP DI,DIRLNK ;Are there anymore?
JNC D8 ;NO, exit
MOV SI,OFFSET C1LNK ;Start with column 1 ptr
D2: MOV BX,SI
MOV SI,[BX] ;SI<-ptr to next entry
OR SI,SI
JZ D7 ;if link=0
MOV AX,SI
MOV DX,DI
XOR CL,CL ;CL <- 0
CMP CL,SIZFLG
JNZ D5 ;If sort by size
CMP CL,DTEFLG
JNZ D4 ;If sort by date/time
CMP CL,EXTFLG
JNZ D3 ;If sort by ext
LEA SI,[SI].NAM
LEA DI,[DI].NAM
MOV CX,1+SIZE NAM+SIZE EXT ;# of bytes
JMP SHORT D6
D3: LEA SI,[SI].EXT ;Sort by extension
LEA DI,[DI].EXT
MOV CX,SIZE EXT ;# of bytes
JMP SHORT D6
D4: LEA SI,[SI].DTE ;Sort by date/time
LEA DI,[DI].DTE
MOV CX,2 ;# of words
STD
REPZ CMPSW
MOV DI,DX
MOV SI,AX
JBE D2
JMP SHORT D7
D5: LEA SI,[SI].SZH ;Sort by size
LEA DI,[DI].SZH
MOV CX,2 ;# of words
STD
REPZ CMPSW
MOV DI,DX
MOV SI,AX
JBE D2
JMP SHORT D7
D6: CLD ;Sort by name.ext
REPZ CMPSB
MOV DI,DX
MOV SI,AX
JBE D2
D7: MOV [DI],SI
MOV [BX],DI
ADD DI,SIZE DIRNTRY ;Point to next entry
JMP D1
D8: RET
SRTDIRB ENDP
SUBTTL
PAGE
; LNKDIRB - LINKS ENTRIES IN DIRBUF
LNKDIRB PROC NEAR ;LINK ENTRIES IN DIRBUF
MOV DI,OFFSET DIRBUF
MOV C1LNK,DI ;Point to 1st entry
MOV CX,NBRFILS ;Set loop counter
DEC CX
LNK1: MOV BX,DI
ADD DI,SIZE DIRNTRY ;Offset to next entry
MOV [BX],DI ;Store ptr
LOOP LNK1 ;Link next entry
MOV [DI],CX ;Last ptr <- null
RET
LNKDIRB ENDP
; SPLTLST - SPLITS LINKED LIST IN HALF
SPLTLST PROC NEAR
MOV CX,NBRFILS ;Get # of entries
SAR CX,1 ; and divide by 2
JZ F2 ;if NBRFILS < 2
ADC CL,0 ;Account for odd #
MOV BX,OFFSET C1LNK
F1: MOV BX,[BX] ;Chain thru list to
LOOP F1 ; last row of column 1.
MOV AX,[BX] ;Get ptr to 1st row of col 2
MOV C2LNK,AX ; C2LNK <- R1,C2 ptr
MOV [BX],CX ;Last row of col 1 <- null
F2: RET
SPLTLST ENDP
SUBTTL GETFREE - GET DISK FREE SPACE
PAGE
GETFREE PROC NEAR ;cluster = allocation unit
MOV DL,DRVNBR ;Get drive #
PUSH DS ;Save DS
DOSCALL @GETVER ;get DOS version number JYF
CMP AL,2 ;is this version 2.0 or higher? JYF
JGE E4 ;yes JYF
;no JYF
DOSCALL @FATAD2 ;Get FAT info from DOS
MOV AH,0 ;AL = sector size
XCHG CX,DX ;Sector size times the
MUL DX ; # sectors/cluster
PUSH AX ;Save cluster size
XOR AX,AX ;Unused clusters = 0
MOV SI,2 ;Skip first 3 clusters
E1: MOV DI,SI ;DI <- cluster #
SHR DI,1 ;Divide cluster number
ADD DI,SI ; by 1.5
MOV DI,[BX+DI] ;Fetch from FAT
TEST SI,1 ;Test if even or odd
JZ E2 ;If even then skip
SHR DI,1 ; else if odd
SHR DI,1 ; right justify the
SHR DI,1 ; cluster number.
SHR DI,1
E2: AND DI,0FFFH ;Mask the low 12 bits
JNZ E3 ;If not 0 then skip, else
INC AX ; increment counter.
E3: INC SI ;Point to next cluster
LOOP E1 ; and go check it.
POP CX ;Get cluster size, times
MUL CX ; # of free clusters
JMP E5 ;skip processing for DOS 2.0 JYF
E4: ;processing for DOS 2.00 JYF
DOSCALL @DSKFSP ;get disk free space JYF
MUL BX ;AX (sectors/clustor) * BX (free clustors) JYF
MOV DX,AX ; JYF
MUL CX ;AX * CX (bytes/clustor)